#include <sdk.h>
#include <scripting/bindings/sc_base_types.h>
#include "ScriptedWizard.h"
#include "wizpage.h"
#include <wx/arrimpl.cpp>

WX_DEFINE_OBJARRAY( Wizards );

namespace {
  PluginRegistrant<Wiz> reg( _T( "ScriptedWizard" ) );
}

DECLARE_INSTANCE_TYPE( Wiz );

Wiz::Wiz() : m_pWizard( nullptr ),
  m_pWizProjectPathPanel( nullptr ),
  m_pWizFilePathPanel( nullptr ),
  m_pWizCompilerPanel( nullptr ),
  m_pWizBuildTargetPanel( nullptr ),
  m_LaunchIndex( 0 ) {
}

Wiz::~Wiz() {
}

void Wiz::OnAttach() {
  Manager::Get()->GetScriptingManager();
  if( !SquirrelVM::GetVMPtr() ) {
    msging( _T( "项目向导已禁用：未初始化脚本" ), _T( "错误" ), wxICON_ERROR );
    return;
  }
  RegisterWizard();
  wxString templatePath = ConfigManager::GetFolder( sdDataGlobal ) + _T( "/templates/wizard/" );
  Manager::Get()->GetLogManager()->LogInf( F( _T( "项目资源路径 %s" ), templatePath.wx_str() ) );
  wxString script = templatePath + _T( "/config.script" );
  if( wxFileExists( script ) ) {
    Manager::Get()->GetScriptingManager()->LoadScript( script );
    try {
      SqPlus::SquirrelFunction<void> f( "RegisterWizards" );
      f();
    } catch( SquirrelError& e ) {
      Manager::Get()->GetScriptingManager()->DisplayErrors( &e );
    }
  }
  m_DefCompilerID = CompilerFactory::GetDefaultCompilerID();
  m_WantDebug = true;
  m_DebugName = _T( "Debug" );
  m_DebugOutputDir = _T( "Debug/" ) ;
  m_DebugObjOutputDir = _T( "/tmp/obj/Debug/" ) ;
  m_WantRelease = true;
  m_ReleaseName = _T( "Release" );
  m_ReleaseOutputDir = _T( "Release/" ) ;
  m_ReleaseObjOutputDir = _T( "/tmp/obj/Release/" );
}

int Wiz::GetCount() const {
  return m_Wizards.GetCount();
}

TemplateOutputType Wiz::GetOutputType( int index ) const {
  cbAssert( index >= 0 && index < GetCount() );
  return m_Wizards[index].output_type;
}

wxString Wiz::GetTitle( int index ) const {
  cbAssert( index >= 0 && index < GetCount() );
  return m_Wizards[index].title;
}

wxString Wiz::GetDescription( int index ) const {
  cbAssert( index >= 0 && index < GetCount() );
  return _T( "通用脚本向导" );
}

wxString Wiz::GetCategory( int index ) const {
  cbAssert( index >= 0 && index < GetCount() );
  return m_Wizards[index].cat;
}

const wxBitmap& Wiz::GetBitmap( int index ) const {
  cbAssert( index >= 0 && index < GetCount() );
  return m_Wizards[index].templatePNG;
}

wxString Wiz::GetScriptFilename( int index ) const {
  cbAssert( index >= 0 && index < GetCount() );
  return m_Wizards[index].script;
}

void Wiz::Clear() {
  if( m_pWizard ) {
    m_pWizard->Destroy();
  }
  m_pWizard = nullptr;
  m_Pages.Clear();
  if( !m_LastXRC.IsEmpty() ) {
    wxXmlResource::Get()->Unload( m_LastXRC );
  }
  m_pWizProjectPathPanel = nullptr;
  m_pWizCompilerPanel = nullptr;
  m_pWizBuildTargetPanel = nullptr;
  m_pWizFilePathPanel = nullptr;
}

CompileTargetBase* Wiz::Launch( int index, wxString* pFilename ) {
  cbAssert( index >= 0 && index < GetCount() );
  static const wxString clearout_wizscripts =  _T( "function BeginWizard(){};\n"
      "function SetupProject(project){return false;};\n"
      "function SetupTarget(target,is_debug){return false;};\n"
      "function SetupCustom(){return false;};\n"
      "function CreateFiles(){return _T(\"\");};\n"
      "function GetFilesDir(){return _T(\"\");};\n"
      "function GetGeneratedFile(index){return _T(\"\");};\n"
      "function GetTargetName() { return _T(\"\"); }\n" );
  Manager::Get()->GetScriptingManager()->LoadBuffer( clearout_wizscripts, _T( "ClearWizState" ) );
  if( m_Wizards[index].output_type == totTarget &&
      !Manager::Get()->GetProjectManager()->GetActiveProject() ) {
    msging( _T( "您需要先打开（或创建）一个项目！" ), _T( "错误" ), wxICON_ERROR );
    return nullptr;
  }
  m_LaunchIndex = index;
  wxString global_commons = ConfigManager::GetFolder( sdDataGlobal ) + _T( "/templates/wizard/common_functions.script" );
  m_LastXRC = m_Wizards[index].xrc;
  if( wxFileExists( m_LastXRC ) ) {
    if( !wxXmlResource::Get()->Load( m_LastXRC ) ) {
      msging( m_Wizards[index].title + _T( " 未能加载xrc资源..." ), _T( "错误" ), wxICON_ERROR );
    }
  } else {
    m_LastXRC.Clear();
  }
  m_pWizard = new wxWizard;
  m_pWizard->Create( Manager::Get()->GetAppWindow(), wxID_ANY,
                     m_Wizards[index].title, m_Wizards[index].wizardPNG,
                     wxDefaultPosition, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER );
  if( !Manager::Get()->GetScriptingManager()->LoadScript( global_commons ) ) {
    Clear();
    InfoWindow::Tip( _T( "未能加载公共函数脚本请检查调试日志以了解详细信息..." ), _T( "错误" ) );
    return nullptr;
  }
  wxString script = ConfigManager::GetFolder( sdDataGlobal ) + _T( "/templates/wizard/" ) + m_Wizards[index].script;
  if( !Manager::Get()->GetScriptingManager()->LoadScript( script ) ) {
    Clear();
    InfoWindow::Tip( _T( "无法加载向导的脚本.\n请检查调试日志以了解详细信息..." ), _T( "错误" ) );
    return nullptr;
  }
  m_WizardScriptFolder = wxEmptyString;
  wxArrayString scriptDirs = wxFileName( script ).GetDirs();
  if( scriptDirs.GetCount() ) {
    m_WizardScriptFolder = scriptDirs[scriptDirs.GetCount() - 1];
  }
  try {
    SqPlus::SquirrelFunction<void> f( "BeginWizard" );
    f();
  } catch( SquirrelError& e ) {
    Manager::Get()->GetScriptingManager()->DisplayErrors( &e );
    Clear();
    return nullptr;
  } catch( M_Code_Exception& e ) {
    e.ShowErrorMessage( false );
    Clear();
    return nullptr;
  }
  if( m_Pages.GetCount() == 0 ) {
    msging( m_Wizards[index].title + _T( " 无法运行..." ), _T( "错误" ), wxICON_ERROR );
    Clear();
    return nullptr;
  }
  if( m_Wizards[index].output_type == totProject && !m_pWizProjectPathPanel ) {
    msging( _T( "此向导缺少以下必需的向导页:\n\n"
                "项目路径选择执行中止..." ), _T( "错误" ), wxICON_ERROR );
    Clear();
    return nullptr;
  }
  Finalize();
  CompileTargetBase* base = nullptr;
  if( m_pWizard->RunWizard( m_Pages[0] ) ) {
    switch( m_Wizards[index].output_type ) {
      case totProject:
        base = RunProjectWizard( pFilename );
        break;
      case totTarget:
        base = RunTargetWizard( pFilename );
        break;
      case totFiles:
        base = RunFilesWizard( pFilename );
        break;
      case totCustom:
        base = RunCustomWizard( pFilename );
        break;
      default:
        break;
    }
  }
  Clear();
  return base;
}

CompileTargetBase* Wiz::RunProjectWizard( wxString* pFilename ) {
  M_Code_Project* theproject = nullptr;
  wxString prjname = GetProjectFullFilename();
  wxFileName fname( prjname );
  wxString prjdir = fname.GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR );
  if( !CreateDirRecursively( prjdir ) ) {
    msging( _T( "无法创建项目目录:\n" ) + prjdir, _T( "错误" ), wxICON_ERROR );
    Clear();
    return nullptr;
  }
  wxString defCompilerID = CompilerFactory::GetDefaultCompilerID();
  CompilerFactory::SetDefaultCompiler( GetCompilerID() );
  theproject = Manager::Get()->GetProjectManager()->NewProject( prjname );
  CompilerFactory::SetDefaultCompiler( defCompilerID );
  if( !theproject ) {
    msging( _T( "无法创建新项目:\n" ) + prjdir, _T( "错误" ), wxICON_ERROR );
    Clear();
    return nullptr;
  }
  theproject->SetTitle( GetProjectTitle() );
  theproject->SetCompilerID( GetCompilerID() );
  if( GetWantDebug() ) {
    ProjectBuildTarget* target = theproject->AddBuildTarget( GetDebugName() );
    if( target ) {
      target->SetCompilerID( GetCompilerID() );
      target->SetIncludeInTargetAll( false );
      target->SetObjectOutput( GetDebugObjectOutputDir() );
    }
  }
  if( GetWantRelease() ) {
    ProjectBuildTarget* target = theproject->AddBuildTarget( GetReleaseName() );
    if( target ) {
      target->SetCompilerID( GetCompilerID() );
      target->SetIncludeInTargetAll( false );
      target->SetObjectOutput( GetReleaseObjectOutputDir() );
    }
  }
  if( theproject->GetBuildTargetsCount() == 0 ) {
    ProjectBuildTarget* target = theproject->AddBuildTarget( _T( "default" ) );
    if( target ) {
      target->SetCompilerID( GetCompilerID() );
      target->SetIncludeInTargetAll( false );
    }
  }
  wxString srcdir;
  try {
    SqPlus::SquirrelFunction<wxString&> f( "GetFilesDir" );
    if( !f.func.IsNull() ) {
      srcdir = f();
    }
    if( !srcdir.IsEmpty() ) {
      wxArrayString tmpsrcdirs = GetArrayFromString( srcdir, _T( ";" ), true );
      for( size_t i = 0; i < tmpsrcdirs.GetCount(); ++i ) {
        CopyFiles( theproject, prjdir, tmpsrcdirs[i] );
      }
    }
  } catch( SquirrelError& e ) {
    Manager::Get()->GetScriptingManager()->DisplayErrors( &e );
    Clear();
    return nullptr;
  }
  try {
    SqPlus::SquirrelFunction<wxString&> f( "GetGeneratedFile" );
    if( !f.func.IsNull() ) {
      wxArrayString files;
      wxArrayString contents;
      int idx = 0;
      while( idx < 50 ) {
        wxString fileAndContents = f( idx++ );
        if( fileAndContents.IsEmpty() ) {
          break;
        }
        wxString tmpFile = fileAndContents.BeforeFirst( _T( ';' ) );
        wxString tmpContents = fileAndContents.AfterFirst( _T( ';' ) );
        tmpFile.Trim();
        tmpContents.Trim();
        if( tmpFile.IsEmpty() || tmpContents.IsEmpty() ) {
          break;
        }
        files.Add( tmpFile );
        contents.Add( tmpContents );
      };
      if( files.GetCount() != 0 && contents.GetCount() == files.GetCount() ) {
        wxArrayInt targetIndices;
        for( int x = 0; x < theproject->GetBuildTargetsCount(); ++x ) {
          targetIndices.Add( x );
        }
        theproject->BeginAddFiles();
        size_t count = files.GetCount();
        for( size_t i = 0; i < count; ++i ) {
          wxString actual = GenerateFile( theproject->GetBasePath(), files[i], contents[i] );
          if( !actual.IsEmpty() ) {
            if( theproject->GetFileByFilename( files[i], true, true ) == NULL ) {
              Manager::Get()->GetLogManager()->DebugLog( _T( "生成的文件 " ) + actual );
              Manager::Get()->GetProjectManager()->AddFileToProject( actual, theproject, targetIndices );
            } else {
              Manager::Get()->GetLogManager()->DebugLog( F( _T( "File %s exists" ), actual.wx_str() ) );
            }
          }
        }
        theproject->EndAddFiles();
      }
    }
  } catch( SquirrelError& e ) {
    Manager::Get()->GetScriptingManager()->DisplayErrors( &e );
    Clear();
    return nullptr;
  }
  Manager::Get()->GetLogManager()->DebugLog( _T( "GetProjectManager" ) );
  try {
    SqPlus::SquirrelFunction<bool> f( "SetupProject" );
    if( !f( theproject ) ) {
      msging( F( _T( "无法设置项目选项:\n%s" ), prjdir.c_str() ), _T( "错误" ), wxICON_ERROR );
      Clear();
      return nullptr;
    }
  } catch( SquirrelError& e ) {
    Manager::Get()->GetScriptingManager()->DisplayErrors( &e );
    Clear();
    return nullptr;
  }
  Manager::Get()->GetLogManager()->DebugLog( _T( "GetProjectManager" ) );
  theproject->Save();
  if( pFilename ) {
    *pFilename = theproject->GetFilename();
  }
  Manager::Get()->GetProjectManager()->GetUI().RebuildTree();
  Manager::Get()->GetProjectManager()->GetUI().GetTree()->Expand( theproject->GetProjectNode() );
  return theproject;
}

CompileTargetBase* Wiz::RunTargetWizard( M_Code_unused wxString* pFilename ) {
  M_Code_Project* theproject = Manager::Get()->GetProjectManager()->GetActiveProject();
  bool isDebug = false;
  wxString targetName;
  if( m_pWizBuildTargetPanel ) {
    targetName = GetTargetName();
    isDebug = GetTargetEnableDebug();
  } else {
    try {
      SqPlus::SquirrelFunction<wxString&> f( "GetTargetName" );
      targetName = f();
      if( targetName == wxEmptyString ) {
        msging( _T( "GetTargetName 返回空字符串。弱点!" ), _T( "错误" ), wxICON_ERROR );
        Clear();
        return nullptr;
      }
    } catch( SquirrelError& e ) {
      Manager::Get()->GetScriptingManager()->DisplayErrors( &e );
      Clear();
      return nullptr;
    }
    isDebug = false;
  }
  ProjectBuildTarget* target = theproject->AddBuildTarget( targetName );
  if( !target ) {
    msging( _T( "未能创建生成目标!" ), _T( "错误" ), wxICON_ERROR );
    Clear();
    return nullptr;
  }
  if( m_pWizBuildTargetPanel ) {
    wxString CompilerId = GetTargetCompilerID();
    if( CompilerId == wxEmptyString ) {
      CompilerId = theproject->GetCompilerID();
      if( CompilerId == wxEmptyString ) {
        CompilerId = CompilerFactory::GetDefaultCompilerID();
        msging( _T( "未指定编译器. 新目标将使用默认编译器." ),
                _T( "已选择回退编译器" ),
                wxOK | wxICON_INFORMATION,
                Manager::Get()->GetAppWindow() );
      } else {
        msging( _T( "未指定编译器. 新目标将使用与项目相同的编译器." ),
                _T( "已选择回退编译器" ),
                wxOK | wxICON_INFORMATION,
                Manager::Get()->GetAppWindow() );
      }
    }
    target->SetCompilerID( CompilerId );
    target->SetIncludeInTargetAll( false );
    target->SetObjectOutput( GetTargetObjectOutputDir() );
    target->SetWorkingDir( GetTargetOutputDir() );
  }
  for( FilesList::iterator it = theproject->GetFilesList().begin(); it != theproject->GetFilesList().end(); ++it ) {
    ProjectFile* pf = *it;
    if( pf ) {
      pf->AddBuildTarget( targetName );
    }
  }
  try {
    SqPlus::SquirrelFunction<bool> f( "SetupTarget" );
    if( !f( target, isDebug ) ) {
      msging( _T( "无法设置目标选项:" ), _T( "错误" ), wxICON_ERROR );
      Clear();
      return nullptr;
    }
  } catch( SquirrelError& e ) {
    Manager::Get()->GetScriptingManager()->DisplayErrors( &e );
    Clear();
    return nullptr;
  }
  return target;
}

CompileTargetBase* Wiz::RunFilesWizard( wxString* pFilename ) {
  try {
    SqPlus::SquirrelFunction<wxString&> f( "CreateFiles" );
    wxString files = f();
    if( files.IsEmpty() ) {
      msging( _T( "向导失败..." ), _T( "错误" ), wxICON_ERROR );
    } else {
      const wxString &filename = files.BeforeFirst( _T( ';' ) );
      if( pFilename ) {
        *pFilename = filename;
      }
      EditorBase *editor = Manager::Get()->GetEditorManager()->GetEditor( filename );
      if( editor && editor->IsBuiltinEditor() ) {
        static_cast<M_Code_Editor*>( editor )->SetEditorStyle();
      }
    }
  } catch( SquirrelError& e ) {
    Manager::Get()->GetScriptingManager()->DisplayErrors( &e );
  }
  Clear();
  return nullptr;
}

CompileTargetBase* Wiz::RunCustomWizard( M_Code_unused wxString* pFilename ) {
  try {
    SqPlus::SquirrelFunction<bool> f( "SetupCustom" );
    if( !f() ) {
      msging( _T( "向导失败..." ), _T( "错误" ), wxICON_ERROR );
    }
  } catch( SquirrelError& e ) {
    Manager::Get()->GetScriptingManager()->DisplayErrors( &e );
  }
  Clear();
  return nullptr;
}

wxString Wiz::GenerateFile( const wxString& basePath, const wxString& filename, const wxString& contents ) {
  wxFileName fname( filename );
  FileType ft = FileTypeOf( fname.GetFullPath() );
  switch( ft ) {
    case ftm_Code_Project:
    case ftm_Code_Workspace:
    case ftExecutable:
    case ftDynamicLib:
    case ftStaticLib:
    case ftResourceBin:
    case ftObject:
      Manager::Get()->GetLogManager()->LogWarning( _T( "尝试生成具有干扰编译的文件!\n忽略请求文件: " ) + fname.GetFullPath() );
      return wxEmptyString;
    default:
      break;
  }
  if( !fname.IsRelative() ) {
    fname.MakeRelativeTo( basePath );
  }
  const wxArrayString& Dirs = fname.GetDirs();
  int IntDirCount = 0;
  for( size_t i = 0; i < Dirs.Count(); i++ ) {
    if( Dirs[i] == _T( ".." ) ) {
      if( IntDirCount-- == 0 ) {
        fname = fname.GetFullName();
        Manager::Get()->GetLogManager()->LogWarning( F( _T( "尝试在项目根目录之外生成文件:\n源: %s\n迁移为:%s" ),
            filename.wx_str(), fname.GetFullPath().wx_str() ) );
        break;
      }
    } else if( Dirs[i] != _T( "." ) ) {
      IntDirCount++;
    }
  }
  fname = basePath + wxFILE_SEP_PATH + fname.GetFullPath();
  if( fname.FileExists() ) {
    wxString query_overwrite;
    query_overwrite.Printf( _T( "警告:\n 向导将覆盖以下现有文件:\n" ) + fname.GetFullPath() );
    if( msging( query_overwrite, _T( "审核" ), wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT ) == wxID_NO ) {
      return fname.GetFullPath();
    }
  }
  wxFileName::Mkdir( fname.GetPath(), 0777, wxPATH_MKDIR_FULL );
  wxFile f( fname.GetFullPath(), wxFile::write );
  if( cbWrite( f, contents + _T( "\n" ), wxFONTENCODING_UTF8 ) ) {
    return fname.GetFullPath();
  }
  return wxEmptyString;
}

void Wiz::CopyFiles( M_Code_Project* theproject, const wxString&  prjdir, const wxString& srcdir ) {
  wxArrayString filesList;
  wxString enumdirs = ConfigManager::GetFolder( sdDataGlobal ) + _T( "/templates/wizard/" ) + srcdir;
  wxString basepath = wxFileName( enumdirs ).GetFullPath();
  if( wxDirExists( enumdirs + _T( "/" ) ) ) {
    wxDir::GetAllFiles( enumdirs, &filesList );
  }
  wxArrayInt targetIndices;
  for( int x = 0; x < theproject->GetBuildTargetsCount(); ++x ) {
    targetIndices.Add( x );
  }
  theproject->BeginAddFiles();
  for( unsigned int i = 0; i < filesList.GetCount(); ++i ) {
    wxString srcfile = filesList[i];
    wxString dstfile = srcfile;
    dstfile.Replace( basepath, prjdir );
    wxFileName fname( dstfile );
    wxString dstdir = fname.GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR );
    CreateDirRecursively( dstdir );
    bool do_copy = true;
    if( wxFileName::FileExists( dstfile ) ) {
      wxString query_overwrite;
      query_overwrite.Printf( _T( "警告:\n 向导将覆盖以下现有文件:\n" ) + wxFileName( dstfile ).GetFullPath() );
      if( msging( query_overwrite, _T( "审核" ), wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT ) != wxID_YES ) {
        do_copy = false;
      }
    }
    if( do_copy ) {
      wxCopyFile( srcfile, dstfile, true );
    }
    fname.MakeRelativeTo( prjdir );
    Manager::Get()->GetProjectManager()->AddFileToProject( fname.GetFullPath(), theproject, targetIndices );
  }
  theproject->EndAddFiles();
}



wxString Wiz::FindTemplateFile( const wxString& filename ) {
  wxString f = ConfigManager::GetFolder( sdDataGlobal ) + _T( "/templates/wizard/" ) + filename;
  return f;
}

TemplateOutputType Wiz::GetWizardType() {
  cbAssert( m_LaunchIndex >= 0 && m_LaunchIndex < GetCount() );
  return m_Wizards[m_LaunchIndex].output_type;
}

void Wiz::FillComboboxWithCompilers( const wxString& name ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxComboBox* win = dynamic_cast<wxComboBox*>( page->FindWindowByName( name, page ) );
    if( win && win->GetCount() == 0 ) {
      for( size_t i = 0; i < CompilerFactory::GetCompilersCount(); ++i ) {
        Compiler* compiler = CompilerFactory::GetCompiler( i );
        if( compiler ) {
          win->Append( compiler->GetName() );
        }
      }
      Compiler* compiler = CompilerFactory::GetDefaultCompiler();
      if( compiler ) {
        win->SetSelection( win->FindString( compiler->GetName() ) );
      }
    }
  }
}

void Wiz::FillContainerWithCompilers( const wxString& name, const wxString& compilerID, const wxString& validCompilerIDs ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxItemContainer* win = dynamic_cast<wxItemContainer*>( page->FindWindowByName( name, page ) );
    if( win && win->GetCount() == 0 ) {
      Wizard::FillCompilerControl( win, compilerID, validCompilerIDs );
    }
  }
}

void Wiz::FillContainerWithSelectCompilers( const wxString& name, const wxString& validCompilerIDs ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxItemContainer* win = dynamic_cast<wxItemContainer*>( page->FindWindowByName( name.IsEmpty() ? _T( "GenericChoiceList" ) : name, page ) );
    if( win ) {
      wxArrayString valids = GetArrayFromString( validCompilerIDs, _T( ";" ), true );
      win->Clear();
      for( size_t i = 0; i < CompilerFactory::GetCompilersCount(); ++i ) {
        Compiler* compiler = CompilerFactory::GetCompiler( i );
        if( compiler ) {
          for( size_t n = 0; n < valids.GetCount(); ++n ) {
            if( CompilerFactory::CompilerInheritsFrom( compiler, valids[n] ) ) {
              win->Append( compiler->GetName() );
              break;
            }
          }
        }
      }
      Compiler* compiler = CompilerFactory::GetDefaultCompiler();
      if( compiler ) {
        win->SetSelection( win->FindString( compiler->GetName() ) );
      }
    }
  }
}

void Wiz::AppendContainerWithSelectCompilers( const wxString& name, const wxString& validCompilerIDs ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxItemContainer* win = dynamic_cast<wxItemContainer*>( page->FindWindowByName( name.IsEmpty() ? _T( "GenericChoiceList" ) : name, page ) );
    if( win ) {
      wxArrayString valids = GetArrayFromString( validCompilerIDs, _T( ";" ), true );
      size_t iItemsCount = win->GetCount();
      wxString nameInItems = _T( ";" );
      for( size_t i = 0; i < iItemsCount; ++i ) {
        nameInItems += win->GetString( i ) + _T( ";" );
      }
      for( size_t i = 0; i < CompilerFactory::GetCompilersCount(); ++i ) {
        Compiler* compiler = CompilerFactory::GetCompiler( i );
        if( compiler ) {
          wxString compilerName = compiler->GetName();
          if( wxNOT_FOUND != nameInItems.Find( _T( ";" ) + compilerName + _T( ";" ) ) ) {
            continue;
          }
          for( size_t n = 0; n < valids.GetCount(); ++n ) {
            if( CompilerFactory::CompilerInheritsFrom( compiler, valids[n] ) ) {
              win->Append( compilerName );
              nameInItems += compilerName + _T( ";" );
              break;
            }
          }
        }
      }
    }
  }
}

void Wiz::EnableWindow( const wxString& name, bool enable ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxWindow* win = page->FindWindowByName( name, page );
    if( win ) {
      win->Enable( enable );
    }
  }
}

void Wiz::SetComboboxSelection( const wxString& name, int sel ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxItemContainer* win = dynamic_cast<wxItemContainer*>( page->FindWindowByName( name, page ) );
    if( win ) {
      win->SetSelection( sel );
    }
  }
}

void Wiz::SetComboboxValue( const wxString& name, const wxString& value ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxComboBox* win = dynamic_cast<wxComboBox*>( page->FindWindowByName( name, page ) );
    if( win ) {
      win->SetValue( value );
    }
  }
}

wxString Wiz::GetComboboxValue( const wxString& name ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxComboBox* win = dynamic_cast<wxComboBox*>( page->FindWindowByName( name, page ) );
    if( win ) {
      return win->GetValue();
    }
  }
  return wxEmptyString;
}


wxString Wiz::GetCompilerFromCombobox( const wxString& name ) {
  int id = GetComboboxSelection( name );
  Compiler* compiler = CompilerFactory::GetCompiler( id );
  if( compiler ) {
    return compiler->GetID();
  }
  return wxEmptyString;
}

wxString Wiz::GetComboboxStringSelection( const wxString& name ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxItemContainer* win = dynamic_cast<wxItemContainer*>( page->FindWindowByName( name, page ) );
    if( win ) {
      return win->GetStringSelection();
    }
  }
  return wxEmptyString;
}

int Wiz::GetComboboxSelection( const wxString& name ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxItemContainer* win = dynamic_cast<wxItemContainer*>( page->FindWindowByName( name, page ) );
    if( win ) {
      return win->GetSelection();
    }
  }
  return -1;
}

int Wiz::GetRadioboxSelection( const wxString& name ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxRadioBox* win = dynamic_cast<wxRadioBox*>( page->FindWindowByName( name, page ) );
    if( win ) {
      return win->GetSelection();
    }
  }
  return -1;
}

void Wiz::SetRadioboxSelection( const wxString& name, int sel ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxRadioBox* win = dynamic_cast<wxRadioBox*>( page->FindWindowByName( name, page ) );
    if( win ) {
      win->SetSelection( sel );
    }
  }
}

int Wiz::GetListboxSelection( const wxString& name ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxListBox* win = dynamic_cast<wxListBox*>( page->FindWindowByName( name, page ) );
    if( win ) {
      return win->GetSelection();
    }
  }
  return -1;
}


wxString Wiz::GetListboxSelections( const wxString& name ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxListBox* lbox = dynamic_cast<wxListBox*>( page->FindWindowByName( name, page ) );
    if( lbox ) {
      wxString result;
      size_t i;
      wxArrayInt selections;
      lbox->GetSelections( selections );
      for( i = 0; i < selections.GetCount(); ++i ) {
        result.Append( F( _T( "%d;" ), selections[i] ) );
      }
      return result;
    }
  }
  return wxEmptyString;
}


wxString Wiz::GetListboxStringSelections( const wxString& name ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxListBox* lbox = dynamic_cast<wxListBox*>( page->FindWindowByName( name, page ) );
    if( lbox ) {
      wxString result;
      size_t i;
      wxArrayInt selections;
      lbox->GetSelections( selections );
      for( i = 0; i < selections.GetCount(); ++i ) {
        result.Append( lbox->GetString( selections[i] ) + _T( ";" ) );
      }
      return result;
    }
  }
  return wxEmptyString;
}


void Wiz::SetListboxSelection( const wxString& name, int sel ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxListBox* win = dynamic_cast<wxListBox*>( page->FindWindowByName( name, page ) );
    if( win ) {
      win->SetSelection( sel );
    }
  }
}

wxString Wiz::GetCheckListboxChecked( const wxString& name ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxCheckListBox* clb = dynamic_cast<wxCheckListBox*>( page->FindWindowByName( name, page ) );
    if( clb ) {
      wxString result;
      unsigned int i;
      for( i = 0; i < clb->GetCount(); ++i ) {
        if( clb->IsChecked( i ) ) {
          result.Append( F( _T( "%u;" ), i ) );
        }
      }
      return result;
    }
  }
  return wxEmptyString;
}

wxString Wiz::GetCheckListboxStringChecked( const wxString& name ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxCheckListBox* clb = dynamic_cast<wxCheckListBox*>( page->FindWindowByName( name, page ) );
    if( clb ) {
      wxString result;
      unsigned int i;
      for( i = 0; i < clb->GetCount(); ++i ) {
        if( clb->IsChecked( i ) ) {
          result.Append( F( _T( "%s;" ), clb->GetString( i ).wx_str() ) );
        }
      }
      return result;
    }
  }
  return wxEmptyString;
}

bool Wiz::IsCheckListboxItemChecked( const wxString& name, unsigned int item ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxCheckListBox* clb = dynamic_cast<wxCheckListBox*>( page->FindWindowByName( name, page ) );
    if( clb ) {
      return clb->IsChecked( item );
    }
  }
  return false;
}

void Wiz::CheckCheckListboxItem( const wxString& name, unsigned int item, bool check ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxCheckListBox* clb = dynamic_cast<wxCheckListBox*>( page->FindWindowByName( name, page ) );
    if( clb ) {
      clb->Check( item, check );
    }
  }
}

void Wiz::CheckCheckbox( const wxString& name, bool check ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxCheckBox* win = dynamic_cast<wxCheckBox*>( page->FindWindowByName( name, page ) );
    if( win ) {
      win->SetValue( check );
    }
  }
}

bool Wiz::IsCheckboxChecked( const wxString& name ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxCheckBox* win = dynamic_cast<wxCheckBox*>( page->FindWindowByName( name, page ) );
    if( win ) {
      return win->IsChecked();
    }
  }
  return false;
}

void Wiz::SetTextControlValue( const wxString& name, const wxString& value ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxTextCtrl* win = dynamic_cast<wxTextCtrl*>( page->FindWindowByName( name, page ) );
    if( win ) {
      win->SetValue( value );
    }
  }
}

wxString Wiz::GetTextControlValue( const wxString& name ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxTextCtrl* win = dynamic_cast<wxTextCtrl*>( page->FindWindowByName( name, page ) );
    if( win ) {
      return win->GetValue();
    }
  }
  return wxEmptyString;
}

void Wiz::SetSpinControlValue( const wxString& name, int value ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxSpinCtrl* win = dynamic_cast<wxSpinCtrl*>( page->FindWindowByName( name, page ) );
    if( win ) {
      win->SetValue( value );
    }
  }
}

int Wiz::GetSpinControlValue( const wxString& name ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxSpinCtrl* win = dynamic_cast<wxSpinCtrl*>( page->FindWindowByName( name, page ) );
    if( win ) {
      return win->GetValue();
    }
  }
  return -1;
}

void Wiz::AddInfoPage( const wxString& pageId, const wxString& intro_msg ) {
  WizPageBase* page = new WizInfoPanel( pageId, intro_msg, m_pWizard, m_Wizards[m_LaunchIndex].wizardPNG );
  if( !page->SkipPage() ) {
    m_Pages.Add( page );
  } else {
    delete page;
  }
}

void Wiz::AddFilePathPage( bool showHeaderGuard ) {
  if( m_pWizFilePathPanel ) {
    return;
  }
  m_pWizFilePathPanel = new WizFilePathPanel( showHeaderGuard, m_pWizard, m_Wizards[m_LaunchIndex].wizardPNG );
  if( !m_pWizFilePathPanel->SkipPage() ) {
    m_Pages.Add( m_pWizFilePathPanel );
  } else {
    delete m_pWizFilePathPanel;
    m_pWizFilePathPanel = nullptr;
  }
}

void Wiz::AddProjectPathPage() {
  if( m_pWizProjectPathPanel ) {
    return;
  }
  m_pWizProjectPathPanel = new WizProjectPathPanel( m_pWizard, m_Wizards[m_LaunchIndex].wizardPNG );
  if( !m_pWizProjectPathPanel->SkipPage() ) {
    m_Pages.Add( m_pWizProjectPathPanel );
  } else {
    delete m_pWizProjectPathPanel;
    m_pWizProjectPathPanel = nullptr;
  }
}

void Wiz::AddCompilerPage( const wxString& compilerID, const wxString& validCompilerIDs, bool allowCompilerChange, bool allowConfigChange ) {
  if( m_pWizCompilerPanel ) {
    return;
  }
  m_pWizCompilerPanel = new WizCompilerPanel( compilerID, validCompilerIDs, m_pWizard, m_Wizards[m_LaunchIndex].wizardPNG, allowCompilerChange, allowConfigChange );
  if( !m_pWizCompilerPanel->SkipPage() ) {
    m_Pages.Add( m_pWizCompilerPanel );
  } else {
    delete m_pWizCompilerPanel;
    m_pWizCompilerPanel = nullptr;
  }
}

void Wiz::AddBuildTargetPage( const wxString& targetName, bool isDebug, bool showCompiler, const wxString& compilerID, const wxString& validCompilerIDs, bool allowCompilerChange ) {
  if( m_pWizBuildTargetPanel ) {
    return;
  }
  m_pWizBuildTargetPanel = new WizBuildTargetPanel( targetName, isDebug, m_pWizard, m_Wizards[m_LaunchIndex].wizardPNG, showCompiler, compilerID, validCompilerIDs, allowCompilerChange );
  if( !m_pWizBuildTargetPanel->SkipPage() ) {
    m_Pages.Add( m_pWizBuildTargetPanel );
  } else {
    delete m_pWizBuildTargetPanel;
    m_pWizBuildTargetPanel = nullptr;
  }
}

void Wiz::AddGenericSingleChoiceListPage( const wxString& pageName, const wxString& descr, const wxString& choices, int defChoice ) {
  WizPageBase* page = new WizGenericSingleChoiceList( pageName, descr, GetArrayFromString( choices, _T( ";" ) ), defChoice, m_pWizard, m_Wizards[m_LaunchIndex].wizardPNG );
  if( !page->SkipPage() ) {
    m_Pages.Add( page );
  } else {
    delete page;
  }
}

void Wiz::AddGenericSelectPathPage( const wxString& pageId, const wxString& descr, const wxString& label, const wxString& defValue ) {
  WizPageBase* page = new WizGenericSelectPathPanel( pageId, descr, label, defValue, m_pWizard, m_Wizards[m_LaunchIndex].wizardPNG );
  if( !page->SkipPage() ) {
    m_Pages.Add( page );
  } else {
    delete page;
  }
}

void Wiz::AddPage( const wxString& panelName ) {
  WizPage* page = new WizPage( panelName, m_pWizard, m_Wizards[m_LaunchIndex].wizardPNG );
  if( !page->SkipPage() ) {
    m_Pages.Add( page );
  } else {
    delete page;
  }
}

void Wiz::Finalize() {
  for( size_t i = 1; i < m_Pages.GetCount(); ++i ) {
    wxWizardPageSimple::Chain( m_Pages[i - 1], m_Pages[i] );
  }
  for( size_t i = 0; i < m_Pages.GetCount(); ++i ) {
    m_pWizard->GetPageAreaSizer()->Add( m_Pages[i] );
  }
  m_pWizard->Fit();
}

void Wiz::AddWizard( TemplateOutputType otype, const wxString& title, const wxString& cat, const wxString& script,
                     const wxString& templatePNG, const wxString& wizardPNG, const wxString& xrc ) {
  for( size_t i = 0; i < m_Wizards.GetCount(); ++i ) {
    WizardInfo& info = m_Wizards[i];
    if( info.output_type == otype && info.title == title ) {
      Manager::Get()->GetLogManager()->Log( F( _T( "向导已注册 跳过... (%s)" ), title.wx_str() ) );
      return;
    }
  }
  wxString tpng = ConfigManager::GetFolder( sdDataGlobal ) + _T( "/templates/wizard/" ) + templatePNG;
  wxString wpng = ConfigManager::GetFolder( sdDataGlobal ) + _T( "/templates/wizard/" ) + wizardPNG;
  wxString _xrc = ConfigManager::GetFolder( sdDataGlobal ) + _T( "/templates/wizard/" ) + xrc;
  WizardInfo info;
  info.output_type = otype;
  info.title = title;
  info.cat = cat;
  info.script = script;
  info.templatePNG = M_Code_LoadBitmap( tpng, wxBITMAP_TYPE_PNG );
  if( info.templatePNG.Ok() && ( info.templatePNG.GetWidth() != 32 || info.templatePNG.GetHeight() != 32 ) ) {
    Manager::Get()->GetLogManager()->LogWarning( F( _T( "调整图像大小 '%s' 为32x32（原始尺寸为 %dx%d)" ),
        tpng.wx_str(), info.templatePNG.GetWidth(), info.templatePNG.GetHeight() ) );
    wxImage temp = info.templatePNG.ConvertToImage();
    temp.Resize( wxSize( 32, 32 ), wxPoint( 0, 0 ), -1, -1, -1 );
    info.templatePNG = wxBitmap( temp );
  }
  info.wizardPNG = M_Code_LoadBitmap( wpng, wxBITMAP_TYPE_PNG );
  info.xrc = _xrc;
  m_Wizards.Add( info );
  wxString typS;
  switch( otype ) {
    case totProject:
      typS = _T( "Project" );
      break;
    case totTarget:
      typS = _T( "Build-target" );
      break;
    case totFiles:
      typS = _T( "File(s)" );
      break;
    case totUser:
      typS = _T( "User" );
      break;
    case totCustom:
      typS = _T( "Custom" );
      break;
    default:
      break;
  }
  Manager::Get()->GetLogManager()->Log( F( typS + _T( " 添加项目向导 '%s'" ), title.wx_str() ) );
}

wxString Wiz::GetProjectPath() {
  if( m_pWizProjectPathPanel ) {
    return m_pWizProjectPathPanel->GetPath();
  }
  return wxEmptyString;
}

wxString Wiz::GetProjectName() {
  if( m_pWizProjectPathPanel ) {
    return m_pWizProjectPathPanel->GetName();
  }
  return wxEmptyString;
}

wxString Wiz::GetProjectFullFilename() {
  if( m_pWizProjectPathPanel ) {
    return m_pWizProjectPathPanel->GetFullFileName();
  }
  return wxEmptyString;
}

wxString Wiz::GetProjectTitle() {
  if( m_pWizProjectPathPanel ) {
    return m_pWizProjectPathPanel->GetTitle();
  }
  return wxEmptyString;
}

wxString Wiz::GetCompilerID() {
  if( m_pWizCompilerPanel && GetWizardType() == totProject ) {
    return m_pWizCompilerPanel->GetCompilerID();
  } else if( GetWizardType() == totTarget && m_pWizBuildTargetPanel ) {
    return m_pWizBuildTargetPanel->GetCompilerID();
  }
  return m_DefCompilerID;
}

bool Wiz::GetWantDebug() {
  if( m_pWizCompilerPanel ) {
    return m_pWizCompilerPanel->GetWantDebug();
  }
  return m_WantDebug;
}

wxString Wiz::GetDebugName() {
  if( m_pWizCompilerPanel ) {
    return m_pWizCompilerPanel->GetDebugName();
  }
  return m_DebugName;
}

wxString Wiz::GetDebugOutputDir() {
  if( m_pWizCompilerPanel ) {
    return m_pWizCompilerPanel->GetDebugOutputDir();
  }
  return m_DebugOutputDir;
}

wxString Wiz::GetDebugObjectOutputDir() {
  if( m_pWizCompilerPanel ) {
    return m_pWizCompilerPanel->GetDebugObjectOutputDir();
  }
  return m_DebugObjOutputDir;
}

bool Wiz::GetWantRelease() {
  if( m_pWizCompilerPanel ) {
    return m_pWizCompilerPanel->GetWantRelease();
  }
  return m_WantRelease;
}

wxString Wiz::GetReleaseName() {
  if( m_pWizCompilerPanel ) {
    return m_pWizCompilerPanel->GetReleaseName();
  }
  return m_ReleaseName;
}

wxString Wiz::GetReleaseOutputDir() {
  if( m_pWizCompilerPanel ) {
    return m_pWizCompilerPanel->GetReleaseOutputDir();
  }
  return m_ReleaseOutputDir;
}

wxString Wiz::GetReleaseObjectOutputDir() {
  if( m_pWizCompilerPanel ) {
    return m_pWizCompilerPanel->GetReleaseObjectOutputDir();
  }
  return m_ReleaseObjOutputDir;
}

wxString Wiz::GetTargetCompilerID() {
  if( m_pWizBuildTargetPanel ) {
    return m_pWizBuildTargetPanel->GetCompilerID();
  }
  return wxEmptyString;
}

bool Wiz::GetTargetEnableDebug() {
  if( m_pWizBuildTargetPanel ) {
    return m_pWizBuildTargetPanel->GetEnableDebug();
  }
  return false;
}

wxString Wiz::GetTargetName() {
  if( m_pWizBuildTargetPanel ) {
    return m_pWizBuildTargetPanel->GetTargetName();
  }
  return wxEmptyString;
}

wxString Wiz::GetTargetOutputDir() {
  if( m_pWizBuildTargetPanel ) {
    return m_pWizBuildTargetPanel->GetTargetOutputDir();
  }
  return wxEmptyString;
}

wxString Wiz::GetTargetObjectOutputDir() {
  if( m_pWizBuildTargetPanel ) {
    return m_pWizBuildTargetPanel->GetTargetObjectOutputDir();
  }
  return wxEmptyString;
}

wxString Wiz::GetFileName() {
  if( m_pWizFilePathPanel ) {
    return m_pWizFilePathPanel->GetFilename();
  }
  return wxEmptyString;
}

wxString Wiz::GetFileHeaderGuard() {
  if( m_pWizFilePathPanel ) {
    return m_pWizFilePathPanel->GetHeaderGuard();
  }
  return wxEmptyString;
}

bool Wiz::GetFileAddToProject() {
  if( m_pWizFilePathPanel ) {
    return m_pWizFilePathPanel->GetAddToProject();
  }
  return false;
}

int Wiz::GetFileTargetIndex() {
  if( m_pWizFilePathPanel ) {
    return m_pWizFilePathPanel->GetTargetIndex();
  }
  return -1;
}

void Wiz::SetFilePathSelectionFilter( const wxString& filter ) {
  if( m_pWizFilePathPanel ) {
    m_pWizFilePathPanel->SetFilePathSelectionFilter( filter );
  }
}

void Wiz::SetCompilerDefault( M_Code_unused const wxString& defCompilerID ) {
  m_DefCompilerID = CompilerFactory::GetDefaultCompilerID();
}

void Wiz::SetDebugTargetDefaults( bool wantDebug,
                                  const wxString& debugName,
                                  const wxString& debugOut,
                                  const wxString& debugObjOut ) {
  m_WantDebug = wantDebug;
  m_DebugName = debugName;
  m_DebugOutputDir = debugOut;
  m_DebugObjOutputDir = debugObjOut;
}

void Wiz::SetReleaseTargetDefaults( bool wantRelease,
                                    const wxString& releaseName,
                                    const wxString& releaseOut,
                                    const wxString& releaseObjOut ) {
  m_WantRelease = wantRelease;
  m_ReleaseName = releaseName;
  m_ReleaseOutputDir = releaseOut;
  m_ReleaseObjOutputDir = releaseObjOut;
}

int Wiz::FillContainerWithChoices( const wxString& name, const wxString& choices ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxItemContainer* win = dynamic_cast<wxItemContainer*>( page->FindWindowByName( name.IsEmpty() ? _T( "GenericChoiceList" ) : name, page ) );
    if( win ) {
      win->Clear();
      wxArrayString items = GetArrayFromString( choices, _T( ";" ) );
      unsigned int nItems = items.GetCount();
      for( unsigned int i = 0; i < nItems; i++ ) {
        win->Append( items[i] );
      }
      return 0;
    }
  }
  return -1;
}

int Wiz::AppendContainerWithChoices( const wxString& name, const wxString& choices ) {
  wxWizardPage* page = m_pWizard->GetCurrentPage();
  if( page ) {
    wxItemContainer* win = dynamic_cast<wxItemContainer*>( page->FindWindowByName( name.IsEmpty() ? _T( "GenericChoiceList" ) : name, page ) );
    if( win ) {
      wxArrayString items = GetArrayFromString( choices, _T( ";" ) );
      size_t iItemsCount = win->GetCount();
      wxString nameInItems = _T( ";" );
      for( size_t i = 0; i < iItemsCount; ++i ) {
        nameInItems += win->GetString( i ) + _T( ";" );
      }
      unsigned int nItems = items.GetCount();
      for( unsigned int i = 0; i < nItems; i++ ) {
        wxString tItemsName = items[i];
        if( wxNOT_FOUND != nameInItems.Find( _T( ";" ) + tItemsName + _T( ";" ) ) ) {
          continue;
        }
        win->Append( tItemsName );
        nameInItems += tItemsName + _T( ";" );
      }
      return 0;
    }
  }
  return -1;
}

wxString Wiz::GetWizardScriptFolder( void ) {
  return m_WizardScriptFolder;
}


void Wiz::RegisterWizard() {
  SqPlus::SQClassDef<Wiz>( "Wiz" ).
  func( &Wiz::AddWizard, "AddWizard" ).
  func( &Wiz::AddInfoPage, "AddInfoPage" ).
  func( &Wiz::AddProjectPathPage, "AddProjectPathPage" ).
  func( &Wiz::AddFilePathPage, "AddFilePathPage" ).
  func( &Wiz::AddCompilerPage, "AddCompilerPage" ).
  func( &Wiz::AddBuildTargetPage, "AddBuildTargetPage" ).
  func( &Wiz::AddGenericSingleChoiceListPage, "AddGenericSingleChoiceListPage" ).
  func( &Wiz::AddGenericSelectPathPage, "AddGenericSelectPathPage" ).
  func( &Wiz::AddPage, "AddPage" ).
  func( &Wiz::SetCompilerDefault, "SetCompilerDefault" ).
  func( &Wiz::SetDebugTargetDefaults, "SetDebugTargetDefaults" ).
  func( &Wiz::SetReleaseTargetDefaults, "SetReleaseTargetDefaults" ).
  func( &Wiz::EnableWindow, "EnableWindow" ).
  func( &Wiz::SetTextControlValue, "SetTextControlValue" ).
  func( &Wiz::GetTextControlValue, "GetTextControlValue" ).
  func( &Wiz::SetSpinControlValue, "SetSpinControlValue" ).
  func( &Wiz::GetSpinControlValue, "GetSpinControlValue" ).
  func( &Wiz::CheckCheckbox, "CheckCheckbox" ).
  func( &Wiz::IsCheckboxChecked, "IsCheckboxChecked" ).
  func( &Wiz::FillComboboxWithCompilers, "FillComboboxWithCompilers" ).
  func( &Wiz::GetCompilerFromCombobox, "GetCompilerFromCombobox" ).
  func( &Wiz::FillContainerWithCompilers, "FillContainerWithCompilers" ).
  func( &Wiz::GetComboboxStringSelection, "GetComboboxStringSelection" ).
  func( &Wiz::GetComboboxSelection, "GetComboboxSelection" ).
  func( &Wiz::SetComboboxSelection, "SetComboboxSelection" ).
  func( &Wiz::SetComboboxValue, "SetComboboxValue" ).
  func( &Wiz::GetComboboxValue, "GetComboboxValue" ).
  func( &Wiz::GetComboboxStringSelection, "GetItemContainerStringSelection" ).
  func( &Wiz::GetComboboxSelection, "GetItemContainerSelection" ).
  func( &Wiz::SetComboboxSelection, "SetItemContainerSelection" ).
  func( &Wiz::GetRadioboxSelection, "GetRadioboxSelection" ).
  func( &Wiz::SetRadioboxSelection, "SetRadioboxSelection" ).
  func( &Wiz::GetListboxSelection, "GetListboxSelection" ).
  func( &Wiz::GetListboxSelections, "GetListboxSelections" ).
  func( &Wiz::GetListboxStringSelections, "GetListboxStringSelections" ).
  func( &Wiz::SetListboxSelection, "SetListboxSelection" ).
  func( &Wiz::GetCheckListboxChecked, "GetCheckListboxChecked" ).
  func( &Wiz::GetCheckListboxStringChecked, "GetCheckListboxStringChecked" ).
  func( &Wiz::IsCheckListboxItemChecked, "IsCheckListboxItemChecked" ).
  func( &Wiz::CheckCheckListboxItem, "CheckCheckListboxItem" ).
  func( &Wiz::GetWizardType, "GetWizardType" ).
  func( &Wiz::FindTemplateFile, "FindTemplateFile" ).
  func( &Wiz::GetProjectPath, "GetProjectPath" ).
  func( &Wiz::GetProjectName, "GetProjectName" ).
  func( &Wiz::GetProjectFullFilename, "GetProjectFullFilename" ).
  func( &Wiz::GetProjectTitle, "GetProjectTitle" ).
  func( &Wiz::GetCompilerID, "GetCompilerID" ).
  func( &Wiz::GetWantDebug, "GetWantDebug" ).
  func( &Wiz::GetDebugName, "GetDebugName" ).
  func( &Wiz::GetDebugOutputDir, "GetDebugOutputDir" ).
  func( &Wiz::GetDebugObjectOutputDir, "GetDebugObjectOutputDir" ).
  func( &Wiz::GetWantRelease, "GetWantRelease" ).
  func( &Wiz::GetReleaseName, "GetReleaseName" ).
  func( &Wiz::GetReleaseOutputDir, "GetReleaseOutputDir" ).
  func( &Wiz::GetReleaseObjectOutputDir, "GetReleaseObjectOutputDir" ).
  func( &Wiz::GetTargetCompilerID, "GetTargetCompilerID" ).
  func( &Wiz::GetTargetEnableDebug, "GetTargetEnableDebug" ).
  func( &Wiz::GetTargetName, "GetTargetName" ).
  func( &Wiz::GetTargetOutputDir, "GetTargetOutputDir" ).
  func( &Wiz::GetTargetObjectOutputDir, "GetTargetObjectOutputDir" ).
  func( &Wiz::GetFileName, "GetFileName" ).
  func( &Wiz::GetFileHeaderGuard, "GetFileHeaderGuard" ).
  func( &Wiz::GetFileAddToProject, "GetFileAddToProject" ).
  func( &Wiz::GetFileTargetIndex, "GetFileTargetIndex" ).
  func( &Wiz::SetFilePathSelectionFilter, "SetFilePathSelectionFilter" ).
  func( &Wiz::FillContainerWithSelectCompilers, "FillContainerWithSelectCompilers" ).
  func( &Wiz::AppendContainerWithSelectCompilers, "AppendContainerWithSelectCompilers" ).
  func( &Wiz::FillContainerWithChoices, "FillContainerWithChoices" ).
  func( &Wiz::AppendContainerWithChoices, "AppendContainerWithChoices" ).
  func( &Wiz::GetWizardScriptFolder, "GetWizardScriptFolder" );
  SqPlus::BindVariable( this, "Wizard", SqPlus::VAR_ACCESS_READ_ONLY );
}


